تؤفر البيرل عدة من الانواع لبنى التكرارية وهي مفيدة لتكرر كود ما في البرنامج ويستعمل باستمرار في البرنامج
تسمى بالبنية التكرارية ذات الشرط المسبق
الصيغة :
while ( CONDITION ) {
statement }
اذا كان الشرط true يتم تنفيذ التعليمات في البلوك وبعد التنفيذ يتم اختبار الشرط مرة اخرى .... وهكذا حتي يصبح الشرط false فعلى سبيل المثال
#!/usr/bin/perl -w
$i = 1;
while($i <= 5) {
print "While:" . $i . "\n";
$i++;
}
print "outside:$i\n";
#!/usr/bin/perl -w $x = <STDIN>; chomp $x; $b = <STDIN>; chomp $b; $q=int(x/b); $r=$x-$b*$q; if(r==0) print " the A IS DIVISIBLE BY B \n";
برنامج يدخل نسق من الأرقام ثم يقوم بعكس النسق بحيث يصبح أخر عدد فيه هو الأول والثاني هوماقبل الأخير مثلاً النسق 123 يحول إلى النسق 321
#!/usr/bin/perl -w
$x = <STDIN>;
chomp $x;
$i = $x;
while($i>=1)
{
print $i%10;
$i=int($i/10);
}إستخدام الدالة int لتحويل من الكسور العشرية الى الصحيحة فهي تزيل جزء الكسور ويعاد جزء الصحيح
خوارزمية القسمة THE DIVISION ALGORITHM نظرية : إذا كان لدينا عددين صحيح y,b ، وكان b اكبر من صفر ، اذا سيكون لدينا عددين q,r بحيث : y=b*q+r q هو حاصل القسمة Quotient . r هو باقي القسمة remainder . b هو المقسوم Divisor . y هو القاسم divident . حيث باقي القسمة r اكبر او يساوي 0 وأقل من العدد b مثال : -21=5*q+r بقسمة -21 على 5 ، سوف نحصل على حاصل القسمة -4 ، والباقي سوف يكون -1 ، ولكن كما ذكرنا في القاعدة السابقة أن الباقي r دائماً يكون موجب ، لذلك نقوم بجمع 5 في الباقي ، ونطرح 1 من حاصل القسمة لذا يكون لدينا q=-5 ، r=4 نطبقها في المعادلة : 4+-5*5 =-21 وهو صحيح . احد الخوازميات المهمة جداً خوارمية القسمة حيث حاصل القسمة الاولة هو 12 وتم حساب باقي القسمة بواسطة القانون الفكره استخدام خوارزمية القسمة y=b*q+r حيث الاساس b=10 123/10=12 3 12/10=1 2 1/10=0 1 q1=q0/b r1=q0-b*q1 q2=q1/b r2=q1-b*q2 q3=q2/b r3=q2-b*q3 qi+1=qi/b ri+1=qi-b*qi+1
ذات الشرط الملحق
الصيغة :
do {
STATEMENTS
} while (CONDITION);
تنفذ التعليمة STATEMENTS ثم يتم اختبار الشرط فإذا كانت نتيجة الاختبار true يعاد تنفيذ التعليمة STATEMENTS قعلى سبيل المثال
#!/usr/bin/perl -w
$i = 1;
do
{
print "While:" . $i . "\n";
$i++;
}
while($i <= 5);
print "outside:$i\n";ذات الشرط المسبق
الصيغة :
until ( CONDITION ) {
statement }عكس while اذا كان الشرط false يتم تنفيذ التعليمات في البلوك ،ثم بعد التنفيذ يتم اختبار الشرط مرة اخرى .... وهكذا حتي يصبح الشرط true
#!/usr/bin/perl -w
$i = 1;
until($i <= 5) {
print "until:" . $i . "\n";
$i++;
}
print "outside:$i\n";
فهو لايدخل الى بلوك التكرار
ذات الشرط الملحق
الصيغة :
do {
STATEMENTS
} until (CONDITION);على سبيل المثال
#!/usr/bin/perl -w
$i = 1;
do
{
print "until:" . $i . "\n";
$i++;
}
until($i <= 5);
print "outside:$i\n";
الصيغة :
for (initialization; CONDITION ; update) {
statement }
initialization القيمة الابتدايئة ، Condition شرط الاستمرار ، update القيمة الجديدة .
حيث تأخذ قيمة متغير الحلقة في القيمة الابتدايئة ويتم اختبار شرط الاستمرار فاذا كان الشرط محقق يتم الدخول الى الحلقة ثم يعطى قيمة المتغير قيمة جديدة ويعاد اختبار الشرط ....وهكذا .
#!/usr/bin/perl -w
for($i = 1; $i <= 5; $i++)
{
print "For:" . $i . "\n";
}
print "outside:$i\n";
بفرض أننا نرغب بحساب الجذر بإستخدام حلقة التكرار for
#!/usr/bin/perl -w
$x = <STDIN>;
chomp $x;
for($i = 1; $i <= $x; $i++)
{
$y=$x/$i;
if($y*$y== $x) print "square root is:" . $y . "\n";
}نبدأ i=1 ثم وضع حاصل قسمة x مع i في y ونستمر في زيادة i حتى يكون مربع y يساوي المدخل لذلك هو الجذر التربيعي لx .
هي من التكرارات المفيده لتسهيل العمل مع القوائم وذلك للمرور خلال المصفوفة او المصفوفة المترابطة الصيغة :
foreach LOOP_VAR (ARRAY) {
STATEMENTS
}
على سبيل المثال المؤثر .. يتضمن قائمة من الاعداد 1 و 2 ....الى 5
#!/usr/bin/perl –w
$n = 1;
foreach $n (1..5) {
print "Foreach:" . $n . "\n";
$n++;
}
للمرورعبر عناصر المصفوفة
#!/usr/bin/perl -w
@array = ("one", "two", "three");
foreach $iterator (@array) {
print "The value of the iterator is now $iterator \n";
}
بنفس المثال مع المتغير الخاص $_ هو الافتراضي في كثير من الحالات
@array = ("one", "two", "three", "four");
for (@array) {
print "The value of the iterator is now $_ \n";
}
نلاحظ استعمال for في الصيغة بدلاً من foreach ، ينفذ مفسر البيرل التعليمات كما لوكانت foreach ،عن طريق استخدام التكررات الاخرى لعرض المصفوفة بإستخدام for
@array = ("one", "two", "three", "four");
for($i=0;$i<scalar(@array);$i++) {
print "The value of the iterator is now $array[$i]\n";
}
والمصفوفات المترابطة يمكن ان نصل الى كل عناصرها باستعمال الدوال keys, values ،فالدالة keys تعيد الفهارس ودالة values تعيد القيمة .
%ages = ("Michael Caine", 39,"Dirty Den", 34,"Angie", 27,
"Willy", "21 in dog years","The Queen Mother", 108);
foreach $person (keys %ages)
{
print "I know the age of $person\n";
}
foreach $age (values %ages)
{
print "Somebody is $age\n";
}
للمرور عبر المصفوفة المترابطة من خلال الفهرس والقيمة في وقتاُ واحد
%ages = ("Michael Caine", 39,"Dirty Den", 34,"Angie", 27,
"Willy", "21 in dog years","The Queen Mother", 108);
foreach $person (keys %ages)
{
print "I know the age of $person is $ages{$person}\n";
}
او للمرور عبر المصفوفة المترابطة من خلال الفهرس والقيمة في وقتاً واحد من خلال الدالة each حيث تقوم باعادة الفهرس والقيمة الذي يلية تستعمل مع while
#!/usr/bin/perl
%array = ( "100", "Green", "200", "Orange");
while (($key, $value) = each(%array)) {
print("$key = $value\n");
}ملاحظة : الاسهل او الاقل شيوعاً طريقة التكرارات عبر الهاش بأستعمال الدالة keys لإعادة قائمة المفاتيح لكن هذة القائمة في الحقيقة تقوم بعمل نسخ من الهاش لذلك لانستطيع تعديل أسماء المفاتيح
#!/usr/bin/perl
# iterate.pl
use strict;
use warnings;
my %hash = ('Key1' => 'Value1', 'Key2' => 'Value2');
# dump of hash
print "$_ => $hash{$_} \n" foreach keys %hash;
ايضاً اذا اردت فرز قائمة المفاتيح بإستخدام الدالة sort
# sorted dump of hash
print "$_ => $hash{$_} \n" foreach sort keys %hash;
هذا بإلنسبة عندما لانهتم بأمر المفاتيح كذلك لايختلف الحال مع القيم بواسطة الدالة values
# print list of sorted values
foreach (sort values %hash) {
print "Value: $_ \n";
}فهي تعيد قائمة القيم التي تنسخ من الهاش ولذلك لايمكن تعديل القيم الاصلية في هذة الطريقة ،اذا كانت تود تعدل القيم الاصلية يمكن عمل ذلك بواسطة هذا التكرار :
# increment all hash values by one
foreach (@hash{keys %hash}) {
$_++;
}في هذا المثال يستخدم مايسمى بالـaliasing بحيث يصبح وسيط المتغير الخاص الافتراضي $_ مباشرتاً أسماًَ مستعار له بدلاً من نسخ القيمة التي تشير اليه.
# print list of sorted values
foreach (sort values %hash) {
print "Value: $_ \n";
}بحيث لانستطيع في هذة الطريقة العودة بسهولة الى المفاتيح ، أن رغبت بالوصول الى القيم المرتبة من خلال keys نقوم بالتالي:
# sort a hash by values
foreach (sort { $hash{$a} cmp $hash{$b} } keys %hash) {
print "$hash{$_} <= $_ \n";
}معرفة هذا الشي مهم للتغير القيم في الهاش ملاحظة اخرى ،المعالجة مع الكلمة المحجوزة foreach تقوم بإنتزاع كل المفاتيح (او القيم ) مرة واحدة فقط ثم التكرار يعمل من خلالهم ،هذا العمل غير كفوء في الذاكرة خصوصاً اذا كان الهاش كبير ، وبالطبع كلما كان الهاش كبير كلما ازدات كلفة فحصه واستخراج الموارد المطلوبة ، لذلك نستطيع العمل مع إجراء بديل من خلال الدالة each التي تعيد المفتاح والقيمة الذي يلية المستخدمة مع while التكرارية
while (($key, $value) = each %hash) {
print "$key => $value \n";
$hash{$key}++;
}الطلب بواسطة الدالة each لإنجاز المفتاح والقيمة تعمل بنفس الدوال keys و values إي لايمكن الوصول المباشر الى الهاش . |
تؤفر البيرل بعض الكلمات المحجوزة لتغير تدفق البرنامج و تستعمل لسيطرة على التكرار
| الكلمة المحجوزة | الوصف |
|---|---|
| last | القفز الى خارج البلوك الحالي |
| next | القفز الى البلوك التالي مع اختبار الشرط مرة اخرى |
| redo | اعد تشغيل البلوك الحالي بدون اختبار الشرط |
| goto | القفز الى label المحدد |
المثال التالي عدة أشكال للتكرارت
#!/usr/bin/perl
use warnings;
use strict;
my $n = 0;
print "With a while loop:\n";
while (++$n < 4) {print "Hello $n \n";}
print "With a foreach loop:\n";
foreach my $n (1..3) { print "Hello $n \n"; }
print "With a bare block and redo: \n";
$n = 1; { print "Hello $n \n";
last if (++$n > 3); redo; }استخدامنا بلوك مجرد bare block في المثال السابق والبنية الشريطة كاالتكرارت ، يحدث التالي في الشرطية if اذا تحقق الشرط فسوف يخرج من البلوك باستعمال last ، واذا لم يتحقق الشرط فسوف يعاد البلوك عن طريق استعمال redo
With a while loop: Hello 1 Hello 2 Hello 3 With a foreach loop: Hello 1 Hello 2 Hello 3 With a bare block and redo: Hello 1 Hello 2 Hello 3
الكلمة المحجوزة next تستعمل لمهام الضروية في التكرارات لتجاهل الكود المتبقي في البلوك المثال التالي يوضح هذا
#!/usr/bin/perl
# config.pl
use warnings;
use strict;
my %config = ();
while (<>) {
chomp; #ازلة السطر الجديد من المتغير الخاص _$ الافتراضي
next if /^\s*$/; # عند احتوى whitespace سيعيد اختبار التكرار
last if /^\s*\#/; #سوف يخرج عند احتوى رمز التعليق
my ($param, $value) = split("=", $_, 2); #split on first '='
print $_,"\n";
unless ($value) {
print ("No value for parameter '$_' \n");
next; # يعيد اختبار التكرار
}
$config{$param} = $value;
}
foreach (sort keys %config) {
print "$_ => $config{$_} \n";
}
الكلمة المحجوزة next هي في لغة السي والجافا continue التي تتجاهل الكود المتبقي في بلوك التكرار ، بينما في لغة البيرل عند تضمين بلوك continue في التكرار الحالي فسوف تنفذه وهنا برنامج يوضح هذا
my $n = 0;
while ($n < 10) {
next unless($n % 2==0);
print "1: $n \n";
} continue {
# 'next' هنا
$n++;
#print "2: $n \n";
}
# 'last' هنا
بامكان اضافة بلوك continue لكل التكرارات التي تصبح جزء من كود التكرار الذي ينفذ بعد تنفيذ جسم التكرار ، على خلاف عندما يحوي بلوك التكرارعلى الكلمة المحجوزة next في هذة الحالة فأن بلوك continue سوف ينفذ بعد اعاءدته الى التكرار.
تعرضنا سابقاً لجملة last , next , redo الكلمة المحجوزة الاخر للقفز goto ، لإستخدام goto أولاً يلزم تحديد label معنون في البرنامج حتى نستطيع القفز اليه نسجل الاسم متبوعاً بنقطتين
my $n = 0;
while ($n < 10) {
goto CONTINUE,unless($n % 2==0);
print $n,"\n";
CONTINUE:
$n++;
}الطريقة السابقة ليست محببه لكن الافضل استخدام next .
بإنشاء label معنون يحق أستخدم الكلمات والارقام لإسماء label بشرط ان لايكون الاسم عبارة عن كلمة محجوزه للغه البيرل
#!/usr/bin/perl
# blockmain.pl
use strict;
use warnings;
# المتغيرات العامة
my $global_variable = "All the World can see Me";
use constant MY_GLOBAL_CONSTANT => "Global Constant";
# هنا كود الرئيسي للبرنامج
MAIN: {
# في داخل البلوك المتغيرات تعرف محلية وليست عامة
my $main_variable = "Not visible outside main block";
print_variables ($main_variable);
}
sub print_variables {
print $global_variable, "\n", MY_GLOBAL_CONSTANT, "\n";
# print $main_variable, "\n"; #خطأ
print $_[0], "\n"; # صحيح
}يبدا البرنامج تعريف المتغيرات العامة والثوابت ،ثم ينفذ المفسر كود MAIN بخلاف الدالة التي لاتنفذ الا بإستدعى ، label في السي الصداقة friendlier ، مما لاشك فية يمكن انشاء دالة main في البيرل كماهي في السي .